#pragma once

//This loader was made by: http://3dgep.com/?p=1053
//I changed it quite a bit to utilize vectors
//I also changed the formatting (such as getting rid of m_* variables)
//I also fixed the capital charecter in the front of all function names

#include "ModelMD5Animation.h"
#include "../../OpenGL.h"
#include "Model.h"

class _ModelMD5 : public _ModelDef
{
public:
    _ModelMD5();
	~_ModelMD5();
	
    bool load(const char* filename);
    bool loadAnim(const char* filename);
    void update(float fDeltaTime);
    void draw(int &index,double scale);
	
protected:
    typedef std::vector<glm::vec3> PositionBuffer;
    typedef std::vector<glm::vec3> NormalBuffer;
    typedef std::vector<glm::vec2> Tex2DBuffer;
    typedef std::vector<GLuint> IndexBuffer;
	
    struct Vertex{
        glm::vec3   pos;
        glm::vec3   normal;
        glm::vec2   tex0;
        int         startWeight;
        int         weightCount;
    };
    typedef std::vector<Vertex> VertexList;
	
    struct Triangle{
        int             indices[3];
    };
    typedef std::vector<Triangle> TriangleList;
	
    struct Weight{
        int             jointID;
        float           bias;
        glm::vec3       pos;
    };
    typedef std::vector<Weight> WeightList;
	
    struct Joint{
        std::string		name;
        int             parentID;
        glm::vec3       pos;
        glm::quat       orient;
    };
    typedef std::vector<Joint> JointList;
	
    struct Mesh{
		std::string		shader;
        // This vertex list stores the vertices in the bind pose.
        VertexList      verts;
        TriangleList    tris;
        WeightList      weights;
		
        // A texture ID for the material
        GLuint          texID;
		
        // These buffers are used for rendering the animated mesh
        PositionBuffer  positionBuffer;   // Vertex position stream
        NormalBuffer    normalBuffer;     // Vertex normals stream
        Tex2DBuffer     tex2DBuffer;      // Texture coordinate set
        IndexBuffer     indexBuffer;      // Vertex index buffer
    };
    typedef std::vector<Mesh> MeshList;
	
    bool prepareMesh(Mesh &mesh);
    bool prepareMesh(Mesh &mesh, const _MD5Animation::FrameSkeleton &skel);
    bool prepareNormals(Mesh &mesh);
    void renderMesh(const Mesh& mesh);
    void renderNormals(const Mesh& mesh);
    void renderSkeleton(const JointList& joints);
	
    bool checkAnimation(const _MD5Animation& animation) const;
	
	
private:
	
    int                 iMD5Version;
    int                 iNumJoints;
    int                 iNumMeshes;
	
    bool                bHasAnimation;
	
    JointList           joints;
    MeshList            meshes;
	
    _MD5Animation        animation;
	
    glm::mat4x4         localToWorldMatrix;
	
	class ElapsedTime{
	public:
		ElapsedTime(float maxTimeStep = 0.03333f);
		float getElapsedTime() const;
		
	private:
		float fMaxTimeStep;
		mutable float fPrevious;
	};
	
	void computeQuatW(glm::quat& quat);
	void removeQuotes(std::string &str);
	int getFileLength(std::istream &file);
	void ignoreLine(std::istream &file, int length);
	
};